home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / emacs / emacs1857 / src_d2.zoo / source / fileio.c < prev    next >
C/C++ Source or Header  |  1991-12-02  |  63KB  |  2,472 lines

  1. /* File IO for GNU Emacs.
  2.    Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU Emacs.
  5.  
  6. GNU Emacs is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GNU Emacs is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Emacs; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /**
  21.  **  (sjk++)  we need the fcntl flags on the ST.
  22.  **/
  23. #ifdef atarist
  24. #include <fcntl.h>
  25. #endif
  26.  
  27. #include <sys/types.h>
  28. #ifdef hpux
  29. /* needed by <pwd.h> */
  30. #include <stdio.h>
  31. #undef NULL
  32. #endif
  33. #include <sys/stat.h>
  34. #include <pwd.h>
  35. #include <ctype.h>
  36. #include <sys/dir.h>
  37. #include <errno.h>
  38.  
  39. #ifndef VMS
  40. extern int errno;
  41. extern char *sys_errlist[];
  42. extern int sys_nerr;
  43. #endif
  44.  
  45. #define err_str(a) ((a) < sys_nerr ? sys_errlist[a] : "unknown error")
  46.  
  47. #ifdef APOLLO
  48. #include <sys/time.h>
  49. #endif
  50.  
  51. #ifdef NULL
  52. #undef NULL
  53. #endif
  54. #include "config.h"
  55. #include "lisp.h"
  56. #include "buffer.h"
  57. #include "window.h"
  58.  
  59. #ifdef VMS
  60. #include <perror.h>
  61. #include <file.h>
  62. #include <rmsdef.h>
  63. #include <fab.h>
  64. #include <nam.h>
  65. #endif
  66.  
  67. #ifdef HAVE_TIMEVAL
  68. #ifdef HPUX
  69. #include <time.h>
  70. #else
  71. #include <sys/time.h>
  72. #endif
  73. #endif
  74.  
  75. #ifdef HPUX
  76. #include <netio.h>
  77. #include <errnet.h>
  78. #endif
  79.  
  80. #ifndef O_WRONLY
  81. #define O_WRONLY 1
  82. #endif
  83.  
  84. #define min(a, b) ((a) < (b) ? (a) : (b))
  85. #define max(a, b) ((a) > (b) ? (a) : (b))
  86.  
  87. /* Nonzero during writing of auto-save files */
  88. int auto_saving;
  89.  
  90. /* Nonzero means, when reading a filename in the minibuffer,
  91.  start out by inserting the default directory into the minibuffer. */
  92. int insert_default_directory;
  93.  
  94. /* On VMS, nonzero means write new files with record format stmlf.
  95.    Zero means use var format.  */
  96. int vms_stmlf_recfm;
  97.  
  98. Lisp_Object Qfile_error, Qfile_already_exists;
  99.  
  100. report_file_error (string, data)
  101.      char *string;
  102.      Lisp_Object data;
  103. {
  104.   Lisp_Object errstring;
  105.  
  106.   if (errno >= 0 && errno < sys_nerr)
  107.     errstring = build_string (sys_errlist[errno]);
  108.   else
  109.     errstring = build_string ("undocumented error code");
  110.  
  111.   /* System error messages are capitalized.  Downcase the initial. */
  112.   XSTRING (errstring)->data[0] = DOWNCASE (XSTRING (errstring)->data[0]);
  113.  
  114.   while (1)
  115.     Fsignal (Qfile_error,
  116.          Fcons (build_string (string), Fcons (errstring, data)));
  117. }
  118.  
  119. DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory,
  120.   1, 1, 0,
  121.   "Return the directory component in file name NAME.\n\
  122. Return nil if NAME does not include a directory.\n\
  123. Otherwise returns a directory spec.\n\
  124. Given a Unix syntax file name, returns a string ending in slash;\n\
  125. on VMS, perhaps instead a string ending in :, ] or >.")
  126.   (file)
  127.      Lisp_Object file;
  128. {
  129.   register unsigned char *beg;
  130.   register unsigned char *p;
  131.  
  132.   CHECK_STRING (file, 0);
  133.  
  134.   beg = XSTRING (file)->data;
  135.   p = beg + XSTRING (file)->size;
  136.  
  137.   while (p != beg && p[-1] != '/'
  138. #ifdef VMS
  139.      && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
  140. #endif /* VMS */
  141.      ) p--;
  142.  
  143.   if (p == beg)
  144.     return Qnil;
  145.   return make_string (beg, p - beg);
  146. }
  147.  
  148. DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, Sfile_name_nondirectory,
  149.   1, 1, 0,
  150.   "Return file name NAME sans its directory.\n\
  151. For example, in a Unix-syntax file name,\n\
  152. this is everything after the last slash,\n\
  153. or the entire name if it contains no slash.")
  154.   (file)
  155.      Lisp_Object file;
  156. {
  157.   register unsigned char *beg, *p, *end;
  158.  
  159.   CHECK_STRING (file, 0);
  160.  
  161.   beg = XSTRING (file)->data;
  162.   end = p = beg + XSTRING (file)->size;
  163.  
  164.   while (p != beg && p[-1] != '/'
  165. #ifdef VMS
  166.      && p[-1] != ':' && p[-1] != ']' && p[-1] != '>'
  167. #endif /* VMS */
  168.      ) p--;
  169.  
  170.   return make_string (p, end - p);
  171. }
  172.  
  173. char *
  174. file_name_as_directory (out, in)
  175.      char *out, *in;
  176. {
  177.   int size = strlen (in) - 1;
  178.  
  179.   strcpy (out, in);
  180.  
  181. #ifdef VMS
  182.   /* Is it already a directory string? */
  183.   if (in[size] == ':' || in[size] == ']' || in[size] == '>')
  184.     return out;
  185.   /* Is it a VMS directory file name?  If so, hack VMS syntax.  */
  186.   else if (! index (in, '/')
  187.        && ((size > 3 && ! strcmp (&in[size - 3], ".DIR"))
  188.            || (size > 3 && ! strcmp (&in[size - 3], ".dir"))
  189.            || (size > 5 && (! strncmp (&in[size - 5], ".DIR", 4)
  190.                 || ! strncmp (&in[size - 5], ".dir", 4))
  191.            && (in[size - 1] == '.' || in[size - 1] == ';')
  192.            && in[size] == '1')))
  193.     {
  194.       register char *p, *dot;
  195.       char brack;
  196.  
  197.       /* x.dir -> [.x]
  198.      dir:x.dir --> dir:[x]
  199.      dir:[x]y.dir --> dir:[x.y] */
  200.       p = in + size;
  201.       while (p != in && *p != ':' && *p != '>' && *p != ']') p--;
  202.       if (p != in)
  203.     {
  204.       strncpy (out, in, p - in);
  205.       out[p - in] = '\0';
  206.       if (*p == ':')
  207.         {
  208.           brack = ']';
  209.           strcat (out, ":[");
  210.         }
  211.       else
  212.         {
  213.           brack = *p;
  214.           strcat (out, ".");
  215.         }
  216.       p++;
  217.     }
  218.       else
  219.     {
  220.       brack = ']';
  221.       strcpy (out, "[.");
  222.     }
  223.       if (dot = index (p, '.'))
  224.     {
  225.       /* blindly remove any extension */
  226.       size = strlen (out) + (dot - p);
  227.       strncat (out, p, dot - p);
  228.     }
  229.       else
  230.     {
  231.       strcat (out, p);
  232.       size = strlen (out);
  233.     }
  234.       out[size++] = brack;
  235.       out[size] = '\0';
  236.     }
  237. #else /* not VMS */
  238.   /* For Unix syntax, Append a slash if necessary */
  239.   if (out[size] != '/')
  240.     strcat (out, "/");
  241. #endif /* not VMS */
  242.   return out;
  243. }
  244.  
  245. DEFUN ("file-name-as-directory", Ffile_name_as_directory,
  246.        Sfile_name_as_directory, 1, 1, 0,
  247.   "Return a string representing file FILENAME interpreted as a directory.\n\
  248. This string can be used as the value of default-directory\n\
  249. or passed as second argument to expand-file-name.\n\
  250. For a Unix-syntax file name, just appends a slash.\n\
  251. On VMS, converts \"[X]FOO.DIR\" to \"[X.FOO]\", etc.")
  252.   (file)
  253.      Lisp_Object file;
  254. {
  255.   char *buf;
  256.  
  257.   CHECK_STRING (file, 0);
  258.   if (NULL (file))
  259.     return Qnil;
  260.   buf = (char *) alloca (XSTRING (file)->size + 10);
  261.   return build_string (file_name_as_directory (buf, XSTRING (file)->data));
  262. }
  263.  
  264. /*
  265.  * Convert from directory name to filename.
  266.  * On VMS:
  267.  *       xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
  268.  *       xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
  269.  * On UNIX, it's simple: just make sure there is a terminating /
  270.  
  271.  * Value is nonzero if the string output is different from the input.
  272.  */
  273.  
  274. directory_file_name (src, dst)
  275.      char *src, *dst;
  276. {
  277.   long slen;
  278. #ifdef VMS
  279.   long rlen;
  280.   char * ptr, * rptr;
  281.   char bracket;
  282.   struct FAB fab = cc$rms_fab;
  283.   struct NAM nam = cc$rms_nam;
  284.   char esa[NAM$C_MAXRSS];
  285. #endif /* VMS */
  286.  
  287.   slen = strlen (src) - 1;
  288. #ifdef VMS
  289.   if (! index (src, '/')
  290.       && (src[slen] == ']' || src[slen] == ':' || src[slen] == '>'))
  291.     {
  292.       /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */
  293.       fab.fab$l_fna = src;
  294.       fab.fab$b_fns = slen + 1;
  295.       fab.fab$l_nam = &nam;
  296.       fab.fab$l_fop = FAB$M_NAM;
  297.  
  298.       nam.nam$l_esa = esa;
  299.       nam.nam$b_ess = sizeof esa;
  300.       nam.nam$b_nop |= NAM$M_SYNCHK;
  301.  
  302.       /* We call SYS$PARSE to handle such things as [--] for us. */
  303.       if (SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL)
  304.     {
  305.       slen = nam.nam$b_esl - 1;
  306.       if (esa[slen] == ';' && esa[slen - 1] == '.')
  307.         slen -= 2;
  308.       esa[slen + 1] = '\0';
  309.       src = esa;
  310.     }
  311.       if (src[slen] != ']' && src[slen] != '>')
  312.     {
  313.       /* what about when we have logical_name:???? */
  314.       if (src[slen] == ':')
  315.         {            /* Xlate logical name and see what we get */
  316.           ptr = strcpy (dst, src); /* upper case for getenv */
  317.           while (*ptr)
  318.         {
  319.           if ('a' <= *ptr && *ptr <= 'z')
  320.             *ptr -= 040;
  321.           ptr++;
  322.         }
  323.           dst[slen] = 0;    /* remove colon */
  324.           if (!(src = egetenv (dst)))
  325.         return 0;
  326.           /* should we jump to the beginning of this procedure?
  327.          Good points: allows us to use logical names that xlate
  328.          to Unix names,
  329.          Bad points: can be a problem if we just translated to a device
  330.          name...
  331.          For now, I'll punt and always expect VMS names, and hope for
  332.